gRPC实现跨语言(golang&&java)服务调用 |
您所在的位置:网站首页 › golang rpc 多client › gRPC实现跨语言(golang&&java)服务调用 |
为何RPC
在微服务这个时代,不论是传输还是内网调用,以及跨语言的传输,RPC都是不二的选择。GRPC是Google基于protocol buffer传输协议开发的一个RPC框架,支持多语言之间的通信,下面,我会基于Java语言和golang语言做一个跨语言调用例子,Java做client端,golang做服务端 计算器proto接口定义: syntax = "proto3"; option go_package = "client"; //请求 message Request { double num1 = 1; double num2 = 2; OperateType opType = 3; } //操作类型 enum OperateType { Addition = 0; Division = 1; Multiplication = 2; Subtraction = 3; } message Response { double result = 1; } //定义服务 service Operate { rpc Calculate (Request) returns (Response); } 生成go源码:官方给go语言的生成提供了插件,用这个命令就可以快速生成go端的相关代码,为了简便期间,我写成了一个简单的脚本: #!/usr/bin/env bash find ./ -name '*.proto'|xargs protoc --go_out=plugins=grpc:.这个脚本的作用是寻找当前文件下的所有proto文件,并在其所在文件夹下生成源码 接口: package main import ( "context" "errors" "google.golang.org/grpc" "log" "net" "testgo/proto" "testgo/service" ) const ( port = ":9543" ) type server struct { } func (server) Calculate(ctx context.Context, in *client.Request) (resp *client.Response, e error) { log.Printf("Received request") defer func() { // 必须要先声明defer,否则不能捕获到panic异常 if err := recover(); err != nil { e = errors.New(err.(string)) // 这里的err其实就是panic传入的内容 } }() c := service.Calculate{Num1: in.Num1, Num2: in.Num2,} var result float64 switch in.OpType { case client.OperateType_Addition: result = c.Operate(service.Addition) case client.OperateType_Division: result = c.Operate(service.Division) case client.OperateType_Multiplication: result = c.Operate(service.Multiplication) case client.OperateType_Subtraction: result = c.Operate(service.Subtraction) } return &client.Response{Result: result,}, nil } func main() { lis, err := net.Listen("tcp", port) if err != nil { log.Fatalf("failed to listen: %v", err) } s := grpc.NewServer() client.RegisterOperateServer(s, &server{}) if err := s.Serve(lis); err != nil { log.Fatalf("failed to serve: %v", err) } }业务代码: package service type Calculate struct { Num1 float64 Num2 float64 } type Operate func(num1, num2 float64) (result float64) //操作接口 func (c Calculate) Operate(op Operate) (result float64) { return op(c.Num1, c.Num2) } package service //定义操作类型 func Addition(num1, num2 float64) (result float64) { return num1 + num2 } func Division(num1, num2 float64) (result float64) { if num2 == 0 { panic("division by zero") } return num1 / num2 } func Multiplication(num1, num2 float64) (result float64) { return num1 * num2 } func Subtraction(num1, num2 float64) (result float64) { return num1 - num2 }如果server端代码有问题的童鞋,可以参考go官方的rpc调用example 编写go client端 package main import ( "context" "google.golang.org/grpc" "log" "testgo/proto" "time" ) const ( address = "localhost:9543" ) func main() { // Set up a connection to the server. conn, err := grpc.Dial(address, grpc.WithInsecure()) if err != nil { log.Fatalf("did not connect: %v", err) } defer conn.Close() c := client.NewOperateClient(conn) // Contact the server and print out its response. ctx, cancel := context.WithTimeout(context.Background(), time.Second) defer cancel() r, err := c.Calculate(ctx, &client.Request{Num1: 1, Num2: 0, OpType: client.OperateType_Division}) if err != nil { log.Fatalf("could not greet: %v", err) } log.Printf("result: %f", r.Result) } 实现java client端: 引入gprc的maven依赖: io.grpc grpc-netty-shaded 1.20.0 io.grpc grpc-protobuf 1.20.0 io.grpc grpc-stub 1.20.0 引入编译proto文件的maven插件: kr.motd.maven os-maven-plugin 1.5.0.Final org.xolstice.maven.plugins protobuf-maven-plugin 0.5.1 com.google.protobuf:protoc:3.7.1:exe:${os.detected.classifier} grpc-java io.grpc:protoc-gen-grpc-java:1.20.0:exe:${os.detected.classifier} compile compile-custom运行命令:mvn clean install 先启动server端: 然后启动client端 |
CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3 |